# -*- coding: utf-8 -*-

"""
Module implementing CDriveTools.
"""
import serial, re

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

from Ui_DriveTools import Ui_MainWindow
from CommSetting import CCommSetting
from CScope import CScope
from CKeypad import *

from About import CAbout

class CDriveTools(QMainWindow, Ui_MainWindow):
    """
    Class documentation goes here.
    """
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget
        @type QWidget
        """
        super(CDriveTools, self).__init__(parent)
        self.setupUi(self)
        
        self.pt = re.compile('^1 +[\dA-Fa-f]{8} +_\w+')
        self.ptAddr = re.compile('[\dA-Fa-f]{8}')
        self.ptName = re.compile('_\w+')
        self.ptMember = re.compile('_\w+__')
        self.ptClass = re.compile('__\d+\w+')
        
        self.scope = CScope()
        self.curveLayout.addWidget(self.scope.GetCurveView())
        
        self.bgChGroup = QButtonGroup()
        self.bgChGroup.addButton(self.rbScpCh1, 0)
        self.bgChGroup.addButton(self.rbScpCh2, 1)
        self.bgChGroup.addButton(self.rbScpCh3, 2)
        self.bgChGroup.addButton(self.rbScpCh4, 3)
        self.rbScpCh1.clicked.connect(self.on_Radio_Clicked)
        self.rbScpCh2.clicked.connect(self.on_Radio_Clicked)
        self.rbScpCh3.clicked.connect(self.on_Radio_Clicked)
        self.rbScpCh4.clicked.connect(self.on_Radio_Clicked)
        self.rbScpCh1.setChecked(True)
        

        self.count = 0        
                
        self.cbScpSign.addItem('U')
        self.cbScpSign.addItem('S')
        
        
        self.keypadDevice = serial.Serial(timeout = 0.1)   
        self.keypadPort = CCommSetting(self.keypadDevice)
        self.keypadTimer = QTimer()
        self.keypadTimer.timeout.connect(self.on_Keypad_Timeout)
        
        self.keypadDisplay = CKeypadDisplay(self.lbKpParamInfo, self.lbKpDisplay)
        self.keypadComm = CKeypadComm(self.keypadPort)
        self.keypad = CKeypad(self.keypadDisplay, self.keypadComm)
        
    def on_Keypad_Timeout(self):
        self.keypad.UpdateDisplay()
            
    def ParseMapRecord(self, record):
        
        match = self.ptAddr.search(record)
        addr = '0x' + match.group()
        
        match = self.ptName.search(record)
        name = match.group()
        
        match = self.ptClass.search(name)
        if match:
            
            cls = match.group()
            
            if cls[3] >= '0' and cls[3] <= '9':
                cls = cls[4:len(cls)]
            else:
                cls = cls[3:len(cls)]
           
            match = self.ptMember.search(name)
            member = match.group()
            member = member[1:len(member) - 2] 
            
            varName = member + '::' + cls
            
        else:
            varName = name[1:len(name)]
        
        return varName + ' ' + addr  
    
    
    def on_Radio_Clicked(self):
        
        ch = self.bgChGroup.checkedId()
        
        data = self.scope.GetDataObject(ch)
        
        self.sbScpSlaveAddr.setValue(data.slaveAddr)
        self.leScpAddr.setText(hex(data.addr)) 
        
        self.cbScpName.setCurrentIndex(self.cbScpName.findText(data.name))
        self.cbScpSign.setCurrentIndex(self.cbScpSign.findText(data.sign))
        
        self.leScpScale.setText(str(data.scale))
        self.leScpOffset.setText(str(data.offset))
    
    
    @pyqtSlot()
    def on_actionLoad_Map_triggered(self):
        """
        Slot documentation goes here.
        """
        file, filter = QFileDialog.getOpenFileName(
        self,
        'Select map file',
        '',
        "Map file(*.map)",
        None,
        QFileDialog.DontUseNativeDialog)
        
        
        if file != None and file != '':

            #self.statusBar.showMessage(file)             #在状态栏显示文件地址
            #Clear items first
            self.cbScpName.clear()
            self.cbScpName.addItem('')
            self.cbKpAddr.clear()
            self.cbKpAddr.addItem('')
            
                        
            for line in open(file):
                
                match = self.pt.match(line)
                if match:
                    item = self.ParseMapRecord(line)
                    
                    # Add to combo
                    self.cbScpName.addItem(item)
                    self.cbKpAddr.addItem(item)
    
    @pyqtSlot()
    def on_actionKeypad_Comm_Port_triggered(self):
        """
        Slot documentation goes here.
        """
        self.keypadPort.Show()
    
    
    @pyqtSlot(bool)
    def on_actionMem_Mode_toggled(self, p0):
        """
        Slot documentation goes here.
        
        @param p0 DESCRIPTION
        @type bool
        """
        # TODO: not implemented yet
        raise NotImplementedError
    
    
    @pyqtSlot(bool)
    def on_actionFast_Mode_toggled(self, p0):
        """
        Slot documentation goes here.
        
        @param p0 DESCRIPTION
        @type bool
        """
        self.scope.SetFastMode(p0)
    
    
    @pyqtSlot(bool)
    def on_btScpConnect_toggled(self, checked):
        """
        Slot documentation goes here.
        
        @param checked DESCRIPTION
        @type bool
        """
        if not checked:
            self.scope.Stop()
            self.btScpHold.setEnabled(False)
            self.btScpHold.setChecked(False)
            
        else:
            
            #text = 'Port = ' + self.commSetting.port + ' '
            #text = text + 'Baud = ' + str(self.commSetting.baud) + '\n'
            #self.label.setText(text)
            
            try:            
                
                self.scope.Start()
                self.btScpHold.setEnabled(True)
                self.btScpHold.setChecked(False)
            
            except Exception as e:
                
                QMessageBox.critical(self, 'Error', str(e),  QMessageBox.Yes)

    
    @pyqtSlot(bool)
    def on_btScpHold_toggled(self, checked):
        """
        Slot documentation goes here.
        
        @param checked DESCRIPTION
        @type bool
        """
        if checked == True:
            self.scope.Finalize()

    
    @pyqtSlot()
    def on_btKpLeft_clicked(self):
        """
        Slot documentation goes here.
        """
        self.keypad.LeftAction()
    
    @pyqtSlot()
    def on_btKpEnter_clicked(self):
        """
        Slot documentation goes here.
        """
        self.keypad.EnterAction()
    
    @pyqtSlot()
    def on_btKpEsc_clicked(self):
        """
        Slot documentation goes here.
        """
        self.keypad.EscAction()
    
    @pyqtSlot()
    def on_btKpUp_clicked(self):
        """
        Slot documentation goes here.
        """
        self.keypad.UpAction()
    
    @pyqtSlot()
    def on_btKpRight_clicked(self):
        """
        Slot documentation goes here.
        """
        self.keypad.RightAction()
    
    @pyqtSlot()
    def on_btKbStop_clicked(self):
        """
        Slot documentation goes here.
        """
        self.keypad.StopAction()
    
    @pyqtSlot(bool)
    def on_btKpConnect_toggled(self, checked):
        """
        Slot documentation goes here.
        
        @param checked DESCRIPTION
        @type bool
        """
        if checked:
            self.keypadTimer.start(100)
        else:
            self.keypadTimer.stop()
            
        self.keypad.SetActive(checked)
    
    @pyqtSlot()
    def on_btKpRun_clicked(self):
        """
        Slot documentation goes here.
        """
        self.keypad.RunAction()
    
    @pyqtSlot()
    def on_btKbDown_clicked(self):
        """
        Slot documentation goes here.
        """
        self.keypad.DownAction()
    
    @pyqtSlot(bool)
    def on_actionNative_Status_Mode_toggled(self, p0):
        """
        Slot documentation goes here.
        
        @param p0 DESCRIPTION
        @type bool
        """
        # TODO: not implemented yet
        raise NotImplementedError
    
    @pyqtSlot()
    def on_actionScope_Comm_Port_triggered(self):
        """
        Slot documentation goes here.
        """
        self.scope.ShowCommSetting()
    
    @pyqtSlot(str)
    def on_cbScpName_currentIndexChanged(self, p0):
        """
        Slot documentation goes here.
        
        @param p0 DESCRIPTION
        @type str
        """
        try:    
            addr = p0.split(' ')[1]
            self.leScpAddr.setText(addr)            
        except:
            None
    
    @pyqtSlot()
    def on_actionAbout_triggered(self):
        """
        Slot documentation goes here.
        """
        about = CAbout(parent = self)
        about.show()
    
    @pyqtSlot()
    def on_btScpApply_clicked(self):
        """
        Slot documentation goes here.
        """
        ch = self.bgChGroup.checkedId()
        
        name = self.cbScpName.currentText()
        
        slaveAddr = self.sbScpSlaveAddr.value()
        
        if name == '':
            name = 'ch' + str(ch + 1)
            chName = name
            
        else:
            chName = name.split(' ')[0]
            
        self.bgChGroup.checkedButton().setText(chName)
            
        addr = self.leScpAddr.text()
        if addr != '':
            if len(addr) > 2 and (addr[0:2] == '0x' or addr[0:2] == '0X'):
                addr = int(addr, 16)
            else:
                try:
                    addr = int(addr)
                except:
                    addr = 0
                    
        else:
            addr = 0
            
        try:
            scale = self.leScpScale.text()
            scale = float(scale)
            
        except:
            scale = 1.0
        
        try:
            offset = self.leScpOffset.text()
            offset = float(offset)
            
        except:
            offset = 0
                    
                    
        size = self.cbScpSize.currentText()
        sign = self.cbScpSign.currentText()
        
        if ch == 0 and addr == 0:
            raise Exception('Addr of ch1 cannot be 0!')
        
        self.scope.UpdateDataAttributes(ch, slaveAddr,  name, addr, size, sign, scale, offset)
    
    @pyqtSlot()
    def on_btKpRead_clicked(self):
        """
        Slot documentation goes here.
        """
        # TODO: not implemented yet
        raise NotImplementedError
    
    @pyqtSlot()
    def on_btKpWrite_clicked(self):
        """
        Slot documentation goes here.
        """
        # TODO: not implemented yet
        raise NotImplementedError
